/**
 * EduVerse Credentials - 可验证凭证(VC)核心实现
 * 
 * 本模块实现了与W3C VC Data Model v2.0兼容的可验证凭证功能，
 * 包括凭证的发行、验证、存储和管理。
 */

const { 
  W3CCredential, 
  CredentialStatusType 
} = require('@0xpolygonid/js-sdk');
const dataIntegrity = require('@digitalcredentials/data-integrity');
const { Ed25519Signature2020 } = require('@digitalcredentials/ed25519-signature-2020');
const { Ed25519VerificationKey2020 } = require('@digitalcredentials/ed25519-verification-key-2020');
const { v4: uuidv4 } = require('uuid');
const crypto = require('crypto');
const base64url = require('base64url');

/**
 * 使用Polygon ID SDK发行凭证
 * 
 * @param {Object} identityWallet - IdentityWallet实例
 * @param {Object} issuerDID - 发行方DID对象
 * @param {Object} claimData - 凭证声明数据
 * @returns {Promise<Object>} 生成的VC
 */
async function issueCredentialWithPolygonId(identityWallet, issuerDID, claimData) {
  const { 
    credentialSchema,
    type,
    credentialSubject,
    expiration,
    revocationOpts
  } = claimData;
  
  // 准备凭证请求对象
  const credentialRequest = {
    credentialSchema,
    type,
    credentialSubject,
    revocationOpts: revocationOpts || {
      type: CredentialStatusType.Iden3ReverseSparseMerkleTreeProof,
      id: `urn:uuid:${uuidv4()}`,
      nonce: Math.floor(Math.random() * 1000000)
    },
    expiration: expiration || undefined
  };
  
  console.log("Issuing credential with Polygon ID...");
  
  // 尝试使用SDK发行凭证
  try {
    if (typeof identityWallet.issueCredential === 'function') {
      const credential = await identityWallet.issueCredential(issuerDID, credentialRequest);
  console.log("Credential issued with ID:", credential.id);
  return credential;
    } else {
      // 备用路径 - 创建模拟凭证
      console.log("使用模拟方法发行凭证");
      const credentialId = `urn:uuid:${uuidv4()}`;
      const now = new Date();
      
      const issuerDidStr = typeof issuerDID === 'string' ? issuerDID : 
                          (issuerDID.string ? issuerDID.string() : 'did:mock:issuer');
      
      const credential = {
        '@context': ["https://www.w3.org/ns/credentials/v2"],
        id: credentialId,
        type: ["VerifiableCredential"].concat(type ? [type] : []),
        issuer: issuerDidStr,
        issuanceDate: now.toISOString(),
        credentialSubject: {
          id: credentialSubject.id,
          ...credentialSubject
        },
        credentialSchema: {
          id: credentialSchema,
          type: "JsonSchemaValidator2018"
        },
        proof: {
          type: "DataIntegrityProof",
          created: now.toISOString(),
          proofValue: "mockSignatureValue",
          proofPurpose: "assertionMethod",
          verificationMethod: `${issuerDidStr}#keys-1`
        }
      };
      
      // 添加过期时间（如果提供）
      if (expiration) {
        credential.expirationDate = expiration;
      }
      
      console.log("模拟凭证已创建，ID:", credential.id);
      return credential;
    }
  } catch (error) {
    console.error("凭证发行失败:", error);
    throw error;
  }
}

/**
 * 添加W3C Data Integrity证明到凭证
 * 
 * @param {Object} credential - 基础VC对象
 * @param {Object} issuerDID - 发行方DID字符串
 * @param {Object} issuerKeyPair - 发行方密钥对
 * @returns {Promise<Object>} 添加了Data Integrity证明的VC
 */
async function addDataIntegrityProof(credential, issuerDidUrl, issuerKeyPair) {
  console.log("Adding Data Integrity proof...");
  
  // 确保凭证有正确的@context
  if (!credential['@context']) {
    credential['@context'] = ["https://www.w3.org/ns/credentials/v2"];
  }
  
  if (!credential['@context'].includes("https://www.w3.org/ns/credentials/v2")) {
    credential['@context'].push("https://www.w3.org/ns/credentials/v2");
  }
  
  // 创建DataIntegrityProof证明套件
  const key = new Ed25519VerificationKey2020({
    id: `${issuerDidUrl}#keys-1`,
    controller: issuerDidUrl,
    privateKeyMultibase: issuerKeyPair.privateKeyMultibase,
    publicKeyMultibase: issuerKeyPair.publicKeyMultibase
  });
  
  const suite = new Ed25519Signature2020({ key });
  
  // 添加证明
  const verifiableCredential = await dataIntegrity.createVerifiableCredential({
    credential: credential,
    suite,
    documentLoader: dataIntegrity.defaultDocumentLoader
  });
  
  console.log("Data Integrity proof added");
  return verifiableCredential;
}

/**
 * 生成状态列表凭证(用于W3C撤销)
 * 
 * @param {number} listSize - 状态列表大小
 * @param {Object} issuerDidUrl - 发行方DID URL
 * @param {Object} issuerKeyPair - 发行方密钥对
 * @returns {Promise<Object>} 状态列表凭证对象
 */
async function createStatusListCredential(listSize, issuerDidUrl, issuerKeyPair) {
  console.log("Creating StatusListCredential...");
  
  // 创建状态位字符串(初始全0，表示都未撤销)
  const bitstring = Buffer.alloc(Math.ceil(listSize / 8), 0);
  const encodedList = base64url.encode(bitstring);
  
  // 创建状态列表凭证
  const statusListCredential = {
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://www.w3.org/ns/credentials/examples/v2"
    ],
    "id": `urn:uuid:${uuidv4()}`,
    "type": ["VerifiableCredential", "StatusList2021Credential"],
    "issuer": issuerDidUrl,
    "issuanceDate": new Date().toISOString(),
    "credentialSubject": {
      "id": `urn:uuid:${uuidv4()}`,
      "type": "StatusList2021",
      "statusPurpose": "revocation",
      "encodedList": encodedList
    }
  };
  
  // 添加证明
  return await addDataIntegrityProof(statusListCredential, issuerDidUrl, issuerKeyPair);
}

/**
 * 添加状态信息到凭证
 * 
 * @param {Object} credential - 基础VC对象
 * @param {string} statusListCredentialUrl - 状态列表凭证URL
 * @param {number} statusListIndex - 状态列表索引
 * @returns {Object} 添加了状态信息的VC
 */
function addCredentialStatus(credential, statusListCredentialUrl, statusListIndex) {
  console.log(`Adding credential status with index ${statusListIndex}...`);
  
  credential.credentialStatus = {
    id: `${statusListCredentialUrl}#${statusListIndex}`,
    type: "BitstringStatusList2021Status",
    statusListIndex: statusListIndex.toString(),
    statusListCredential: statusListCredentialUrl
  };
  
  return credential;
}

/**
 * 验证W3C Data Integrity证明
 * 
 * @param {Object} credential - 带证明的VC对象
 * @returns {Promise<boolean>} 验证结果
 */
async function verifyDataIntegrityProof(credential) {
  try {
    console.log("Verifying Data Integrity proof...");
    
    const suite = new Ed25519Signature2020();
    
    const result = await dataIntegrity.verifyCredential({
      credential,
      suite,
      documentLoader: dataIntegrity.defaultDocumentLoader
    });
    
    console.log("Verification result:", result.verified);
    return result.verified;
  } catch (error) {
    console.error("Verification error:", error);
    return false;
  }
}

/**
 * 检查凭证撤销状态(W3C Bitstring Status List)
 * 
 * @param {Object} credential - 待检查的VC对象
 * @param {Function} fetchStatusList - 获取状态列表的函数
 * @returns {Promise<boolean>} true表示未撤销，false表示已撤销
 */
async function checkRevocationStatus(credential, fetchStatusList) {
  try {
    if (!credential.credentialStatus || 
        credential.credentialStatus.type !== "BitstringStatusList2021Status") {
      console.warn("Credential has no BitstringStatusList2021Status");
      return true; // 没有撤销信息视为未撤销
    }
    
    const { statusListCredential, statusListIndex } = credential.credentialStatus;
    console.log(`Checking revocation status at index ${statusListIndex}...`);
    
    // 获取状态列表凭证
    const statusListCredentialObj = await fetchStatusList(statusListCredential);
    
    // 验证状态列表凭证
    const isValid = await verifyDataIntegrityProof(statusListCredentialObj);
    if (!isValid) {
      throw new Error("Status list credential signature invalid");
    }
    
    // 解码位字符串
    const encodedList = statusListCredentialObj.credentialSubject.encodedList;
    const bitstring = base64url.toBuffer(encodedList);
    
    // 检查指定位置的状态
    const index = parseInt(statusListIndex, 10);
    const bytePos = Math.floor(index / 8);
    const bitPos = index % 8;
    
    if (bytePos >= bitstring.length) {
      throw new Error("Status index out of range");
    }
    
    const isRevoked = ((bitstring[bytePos] >> bitPos) & 1) === 1;
    console.log("Revocation status:", isRevoked ? "Revoked" : "Not revoked");
    
    return !isRevoked;
  } catch (error) {
    console.error("Error checking revocation status:", error);
    throw error;
  }
}

/**
 * 创建可验证演示(VP)
 * 
 * @param {Object|Array} credentials - 单个VC或VC数组
 * @param {string} holderDid - 持有者DID
 * @param {Object} holderKeyPair - 持有者密钥对
 * @param {Object} options - VP选项，如challenge和domain
 * @returns {Promise<Object>} 生成的VP
 */
async function createVerifiablePresentation(credentials, holderDidUrl, holderKeyPair, options = {}) {
  console.log("Creating Verifiable Presentation...");
  
  const presentation = {
    "@context": ["https://www.w3.org/ns/credentials/v2"],
    "type": ["VerifiablePresentation"],
    "holder": holderDidUrl,
    "verifiableCredential": Array.isArray(credentials) ? credentials : [credentials]
  };
  
  // 创建证明套件
  const key = new Ed25519VerificationKey2020({
    id: `${holderDidUrl}#keys-1`,
    controller: holderDidUrl,
    privateKeyMultibase: holderKeyPair.privateKeyMultibase,
    publicKeyMultibase: holderKeyPair.publicKeyMultibase
  });
  
  const suite = new Ed25519Signature2020({ key });
  
  // 添加证明
  const verifiablePresentation = await dataIntegrity.createVerifiablePresentation({
    presentation,
    challenge: options.challenge,
    domain: options.domain,
    suite,
    documentLoader: dataIntegrity.defaultDocumentLoader
  });
  
  console.log("Verifiable Presentation created");
  return verifiablePresentation;
}

/**
 * 在VP中嵌入ZKP
 * 
 * @param {Object} presentation - 基础VP对象
 * @param {Object} zkProof - ZKP信息
 * @param {string} circuitId - 电路ID
 * @returns {Object} 嵌入了ZKP的VP
 */
function embedZKPInPresentation(presentation, zkProof, circuitId) {
  console.log("Embedding ZKP in presentation...");
  
  // 确保proof是数组
  if (!presentation.proof) {
    presentation.proof = {};
  }
  
  // 嵌入ZKP信息
  presentation.proof.zkp = {
    circuitId,
    proofData: {
      proof: zkProof.proof,
      publicSignals: zkProof.publicSignals
    }
  };
  
  return presentation;
}

module.exports = {
  issueCredentialWithPolygonId,
  addDataIntegrityProof,
  createStatusListCredential,
  addCredentialStatus,
  verifyDataIntegrityProof,
  checkRevocationStatus,
  createVerifiablePresentation,
  embedZKPInPresentation
}; 